#include <QXmlSimpleReader>
#include <QXmlInputSource>
#include <QMessageBox>

//#include "environment.h"
#include "datasource.h"

#include "globals.h"
#include "alarm.h"


int CEnvironment::load(QString filename)
{

    qDebug() << "Environment: loading configuration from " << filename;
    QFile file(filename);
    if (!file.open(QIODevice::ReadOnly)) return -1;

    QXmlSimpleReader xmlReader;
    QXmlInputSource *source = new QXmlInputSource(&file);

    QDomDocument doc;

    QString errmsg;
    int errline, errcol;

    bool ok = doc.setContent(source, &xmlReader, &errmsg, &errline, &errcol);

    if (!ok)
    {
         //QMessageBox::information(0, "openXml", errmsg);
         qDebug() << "Error reading config file:\"" << errmsg << "\"  at line: " << errline << " and column: " << errcol;
         return -1;
    }

    file.close();

    if (doc.hasChildNodes())
    {
        QDomNodeList nodelist = doc.childNodes();
        
        for (int i=0;i<nodelist.count(); i++)
        {
                QDomNode node = nodelist.item(i);
                if ((node.nodeName()) == "settings")
                {
                    QDomNodeList list=node.childNodes();
                        readSettingsNode(list);
                }

         }
     }

    qDebug() << "Environment: Loading configuration finished.";
    return 0;
}

int CEnvironment::readSettingsNode( QDomNodeList &lst )
{
       for (int i=0;i<lst.count(); i++)
         {
                QDomNode node = lst.item(i);
                if ((node.nodeName()) == "parameters")
                {
                    QDomNodeList list=node.childNodes();
                        readParametersNode(list);
                }

                if ((node.nodeName()) == "global")
                {
                    QDomNodeList list=node.childNodes();
                        readGlobalNode(list);
                }

                if ((node.nodeName()) == "gui")
                {
                    QDomNodeList list=node.childNodes();
                        readGuiNode(list);
                }

                /*if ((node.nodeName()) == "expressions")
                {
                        readExpressionsNode(node);
                }*/

         }
       return 0;
}

int CEnvironment::readGuiNode( QDomNodeList &lst )
{
   /* for (int i=0;i<lst.count(); i++)
    {
        QDomNode node = lst.item(i);

        if (node.nodeName() == "title")
            guiTitle = node.toElement().text();

        if (node.nodeName()=="cellwidth1")
            cellWidth1=node.toElement().text().toInt();

        if (node.nodeName()=="cellwidth2")
            cellWidth2=node.toElement().text().toInt();
        if (node.nodeName()=="cellwidth3")
            cellWidth3=node.toElement().text().toInt();

        if (node.nodeName()=="cellheight")
            cellHeight=node.toElement().text().toInt();

    }*/
    return 0;
}

int CEnvironment::readGlobalNode( QDomNodeList &lst )
{
    for (int i=0;i<lst.count(); i++)
    {
         QDomElement node = lst.item(i).toElement();
         if (node.nodeName() == "log")
         {
             globals->log.setDirectory(node.toElement().attribute("directory"));
             globals->log.setInterval(1000*node.toElement().attribute("interval","60").toInt());
         }

         if (node.nodeName() == "sms")
         {
             globals->SMSLogFilename = node.toElement().attribute("logfilename","sms.txt");
         }

         if (node.nodeName() == "userlist")
         {
             QDomNodeList childs = node.childNodes();
             for (int j=0;j<childs.count(); j++)
             {
                 QDomElement child = childs.item(j).toElement();

                 if (child.nodeType() != QDomNode::ElementNode) continue;
                 if (child.nodeName() == "user")
                 {
                     CRecipient *r = new CRecipient;
                     r->name  = child.attribute("name");
                     r->phone = child.attribute("phone");
                     globals->userBase.addUser(r);
                 }

             }
         };

         if (node.nodeName() == "usergroups")
         {
             QDomNodeList childs = node.childNodes();
             for (int j=0;j<childs.count(); j++)
             {
                 QDomNode child = childs.item(j);

                 if (child.nodeType() != QDomNode::ElementNode) continue;
                 if (child.nodeName() == "group")
                 {
                     QString users = child.toElement().attribute("members");
                     QStringList u = users.split(";",QString::SkipEmptyParts);
                     QString q;
                     foreach(q,u)
                     {
                         globals->userBase.addUserToGroup(q,child.toElement().attribute("name"));
                     }
                 }

             }
         };

        /* if (node.nodeName() == "sensor-fail-recipients")
	 {
	    if (!sensorFailAlarm) continue;
	    QDomNodeList childs = node.childNodes();
	    for (int j=0;j<childs.count(); j++)
	    {
		QDomNode child = childs.item(j);

		if (child.nodeType() != QDomNode::ElementNode) continue;
		CRecipient * rec = getRecipient(child.nodeName());
		if (rec) sensorFailAlarm->addRecipient(rec);
	    }
         }*/

         if (node.nodeName() == "owen")
         {
             if (!globals->setupOwen(node.toElement().attribute("baud","0").toInt(),
                               node.toElement().attribute("port","0").toInt()))
                 QMessageBox::information(NULL,"Owen error","Setup owen failed");
         }

         if (node.nodeName() == "gsm")
         {          
             if (!globals->setupModem(node.toElement().attribute("baud","-1").toInt(),
                                node.toElement().attribute("port","-1").toInt()))
                 QMessageBox::information(NULL,"GSM error","Setup GSM-modem failed");;
         }
    }
    return 0;
}

int CEnvironment::readParametersNode( QDomNodeList &lst )
{
    for (int i=0;i<lst.count(); i++)
         {
                QDomNode node = lst.item(i);
                if ((node.nodeName()) == "param")
                     readParamNode(node);

         }
    return 0;
}



bool CEnvironment::readParamNode( QDomNode &inode )
{
    QDomElement node = inode.toElement();
    if (!node.hasAttributes()) return 0;
    if (!node.hasAttribute("name")) return 0;

    QString paramname = node.attribute("name");
    QString paramgroup = node.attribute("group");

    CTechParameter *param = new CTechParameter(paramname,paramgroup);

    param->archFilename = node.attribute("log");

    if (node.hasChildNodes())
    {
        QDomNodeList childList = node.childNodes();
        for (int i=0;i<childList.count(); i++)
        {
            QDomElement child=childList.item(i).toElement();
            if (child.nodeName() == "alarm")
            {
                if (!child.hasAttribute("cond") ||
                        !child.hasAttribute("failvalue") ||
                        !child.hasAttribute("text") ||
                        !child.hasAttribute("group")
                        )
                {
                    qWarning() << "Bad alarm xml tag at" << paramname <<".";
                    continue;
                }
                FAlarm al;
                QString cond = child.attribute("cond");
                if (cond == "l") al.condition = FAlarm::Lower;
                else
                    if (cond == "g") al.condition = FAlarm::Greater;
                    else
                    {
                        qWarning() << "Bad condition in alarm at" << paramname <<".";
                        continue;
                    }

                bool ok;
                al.failValue = child.attribute("failvalue").toDouble(&ok);
                if (!ok)
                {
                    {
                        qWarning() << "Bad value in alarm at" << paramname <<".";
                        continue;
                    }
                }

                if (child.hasAttribute("normalvalue"))
                {
                    double tmp = child.attribute("normalvalue").toInt(&ok);
                    if (ok) al.normalValue = tmp;
                    else al.normalValue = al.failValue;
                }
                else al.normalValue = al.failValue;

                al.parent = param;
                al.message = child.attribute("text");
                al.recipientGroup=child.attribute("group");

                if (child.hasAttribute("normaltext"))
                {
                    al.messageOnReturn = child.attribute("normaltext");
                }

                int tmp;
                if (child.hasAttribute("waittime"))
                {
                     tmp = child.attribute("waittime").toInt(&ok);
                     if (ok) al.waitTime = tmp;
                }

                if (child.hasAttribute("messages"))
                {
                    tmp = child.attribute("messages").toInt(&ok);
                    if (ok) al.messagesCount = tmp;
                }

                if (child.hasAttribute("sendinterval"))
                {
                    tmp = child.attribute("sendinterval").toInt(&ok);
                    if (ok) al.sendInterval = tmp;
                }

                globals->alarms.push_back(new FAlarm(al));


            }
            if (child.nodeName() == "source")
            {
                param->setSource(dataSourceFactory->create(child.toElement().attribute("type"),
                                                   child.toElement().attribute("param")));
            }
        }


    }
    globals->parameters.push_back(param);
    return true;
}

/*
CAlert* CEnvironment::readAlertNode(QDomNode &node)
{
    double value;
    double hyst;
    QString range;
    QString message;

    if (!node.toElement().hasAttribute("value")) return 0;
    if (!node.toElement().hasAttribute("hyst"))  return 0;
    if (!node.toElement().hasAttribute("range")) return 0;

    value = node.toElement().attribute("value","0").toDouble();
    hyst  = node.toElement().attribute("hyst","0").toDouble();
    range = node.toElement().attribute("range","none");

    CAlert *al=NULL;

    if (range == "low")  al = CAlert::lowAlert(value,hyst);
    if (range == "hi")   al = CAlert::hiAlert(value,hyst);

    if (al == NULL) return 0;


    if (!node.hasChildNodes())
    {
        delete al;
        return 0;
    }
    QDomNodeList childs = node.childNodes();
    for (int i=0; i<childs.count(); i++ )
    {
           QDomNode child = childs.item(i);
           if (child.nodeName() == "text")
               al->setMessage(child.toElement().text());

           if (child.nodeName() == "recipients")
           {
                QDomNodeList childs = child.childNodes();
                for (int j=0; j<childs.count(); j++)
                {
                    QDomNode child = childs.item(j);
                    if (child.nodeType() != QDomNode::ElementNode) continue;

                    QString recipient = child.nodeName();
                    CRecipient * rec = getRecipient(recipient);
                    if (rec)  al->addRecipient(rec);
                }
           }
    }

    return al;
};*/


/*
int CEnvironment::readExpressionsNode(QDomNode & node)
{
    QDomNodeList list = node.childNodes();
    for(int i =0; i<list.count(); i++)
    {
        QDomNode child = list.item(i);
        if (child.nodeType() != QDomNode::ElementNode) continue;
        if (child.nodeName()=="exp")
        {
            CExpression * exp = readExpressionNode(child);
            if (exp) Expressions.push_back(exp);
        }
    }
    return 0;
};
CExpression* CEnvironment::readExpressionNode(QDomNode & node)
{
    if (!node.toElement().hasAttribute("name")) return 0;
    if (node.toElement().attribute("name","null") == "osmos")
    {
        QDomElement enabled = node.firstChildElement("enabled");
        QDomElement conduct = node.firstChildElement("conduct");
        QDomElement checktime = node.firstChildElement("checktime");
        QDomElement value = node.firstChildElement("value");
        QDomElement message = node.firstChildElement("message");


        if (enabled.isNull()) return 0;
        if (!enabled.hasAttribute("group")) return 0;
        if (!enabled.hasAttribute("name")) return 0;

        if (conduct.isNull()) return 0;
        if (!conduct.hasAttribute("group")) return 0;
        if (!conduct.hasAttribute("name")) return 0;

        CTechParameter *penabled = findParameter(enabled.attribute("group"),enabled.attribute("name"));
        if (!penabled) return 0;
        CTechParameter * pconduct = findParameter(conduct.attribute("group"),conduct.attribute("name"));
        if (!pconduct) return 0;

        if (value.isNull()) return 0;
        if (checktime.isNull()) return 0;

        bool ok;
        double dvalue= value.text().toDouble(&ok);
        if (!ok) return 0;

        unsigned int ctime = checktime.text().toInt(&ok);
        if (!ok) return 0;

        if (message.isNull()) return 0;
        QString Message = message.text();

        CExpression * exp = CExpression::createOsmos(Message,pconduct,penabled,dvalue,ctime);

        QDomNode recip = node.firstChildElement("recipients");
        if (recip.isNull())
        {
             delete exp;
             return 0;
        }
        QDomNodeList list = recip.childNodes();
        if (list.isEmpty())
        {
            delete exp;
            return 0;
        }
        for (int i=0; i<list.count(); i++)
        {
            QDomNode child = list.item(i);
            if (child.nodeType() != QDomNode::ElementNode) continue;
            CRecipient * rep = getRecipient(child.nodeName());
            if (rep) exp->addRecipient(rep);
        }
     //   QMessageBox::information(0,"Success","Expression osmos successfully loaded");
        return exp;
    }
    return 0;
};
*/
